# -*- coding: utf-8 -*-
# $Id: sqlpipe.py 63 2009-03-17 15:19:51Z 4glitch $

from twisted.internet.protocol import Factory, Protocol, DatagramProtocol
from twisted.enterprise import adbapi
from datetime import datetime
import re


date_re = re.compile('[ADFJMNOS][a-z]{2} [0-9]{1,2}')
time_re = re.compile('([0-9]{2}:){2}[0-9]{2}')
year = datetime.today().year


class SQLPipe(DatagramProtocol):
    
    def __init__(self, factory):
        self.factory = factory
    
    def datagramReceived(self, msg, (host, port)):
        
        values = self._split_datagram(msg) # this may be done with deferred
        if values:
            values.update({"host": host})
            self.factory.passQuery("INSERT INTO `grdlog_event` "
                                   "(`date`, `time`, `host`,"
                                   " `program`, `pid`, `severity`,"
                                   " `facility`, `message`) VALUES "
                                   "(%(date)s, '%(time)s', '%(host)s',"
                                   " '%(program)s', %(pid)s, %(severity)s,"
                                   " %(facility)s, %(message)r)" % values)
    
    def _split_datagram(self, msg):
        if msg[0] == '<':
            next = msg.find('>', 1, 5)
            if next > 0:
                now = datetime.now()
                pri, msg = int(msg[1:next]), msg[next+1:]
                
                match = date_re.match(msg)
                if match and match.start() == 0:
                    next = match.end()
                    date = "str_to_date('%(date)s %(year)s','%%b %%e %%Y')" % {
                        "date": msg[:next],
                        "year": str(year)
                        }
                    msg = msg[next+1:]
                    match = time_re.match(msg)
                    if match and match.start() == 0:
                        next = match.end()
                        time, msg = msg[:next], msg[next+1:]
                    else:
                        time = now.strftime('%H:%M:%S')
                else:
                    time = now.strftime('%H:%M:%S')
                    date = repr(now.strftime('%Y-%m-%d'))
                
                next = msg.find(':')
                pid = 'NULL'
                if next > 0 and msg[:next].find(' ') == -1:
                    program, msg = msg[:next], msg[next+1:].strip()
                    try:
                        program, pid = program.split('[')
                        pid, rest = pid.split(']')
                        if rest != '': raise ValueError
                    except ValueError:
                        pass
                else:
                    program = ''

            return {"severity": pri & 7,
                    "facility": (pri & 248) >> 3,
                    "date": date,
                    "time": time,
                    "program": program,
                    "pid": pid,
                    "message": msg}
        else:
            return None


class SQLFactory(Factory):
    
    def passQuery(self, query):
        self.pool.runOperation(query)
    
    def __init__(self, lib, **dsn):
        self.pool = adbapi.ConnectionPool(lib, **dsn)
